/**
 * 
 */
package cn.xiazhengxin.blog.util;

import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.ImageLine;
import ar.com.hjg.pngj.PngWriter;

/**
 * @author sharl
 * 
 */
public class GenPng {
	int cols = 10;
	int rows = 20;
	int bitdepth = 5;
	boolean alpha = true;

	public void Create() {
		PngWriter writer = new PngWriter("/valcode.png", new ImageInfo(cols,
				rows, bitdepth, alpha));
		writer.setOverrideFile(true);
		Process(writer);
		writer.end();
	}

	private void Process(PngWriter png) {
		int cols = png.imgInfo.cols;
		int rows = png.imgInfo.rows;
		boolean alpha = png.imgInfo.alpha;
		int channels = png.imgInfo.channels;
		int valuesPerRow = png.imgInfo.samplesPerRow;
		ImageLine iline = new ImageLine(png.imgInfo);
		iline.setRown(0);
		iline.setValD(0, 1.0);
		iline.setValD(1, 1.0);
		iline.setValD(2, 0.0);

		iline.setValD(valuesPerRow - channels, 0);
		iline.setValD(valuesPerRow - channels + 1, 1.0);
		iline.setValD(valuesPerRow - channels + 2, 0);

		for (int j = 1; j < cols - 1; j++) {
			iline.setValD(j * channels, 1.0);
			iline.setValD(j * channels + 1, 1.0);
			iline.setValD(j * channels + 2, 1.0);
		}
		if (alpha)
			addAlpha(iline);
		png.writeRow(iline);
		iline.incRown();

		for (int j = 1; j < cols - 1; j++) {
			iline.setValD(j * channels, 0.0);
			iline.setValD(j * channels + 1, 0.0);
			iline.setValD(j * channels + 2, 0.0);
		}
		if (alpha)
			addAlpha(iline);
		png.writeRow(iline);
		iline.incRown();

		for (; iline.getRown() < rows; iline.incRown()) {
			for (int j = 1; j < cols - 1; j++) {
				iline
						.setValD(j * channels, clamp((2 * j / cols) - 0.3, 0,
								1.0));
				iline.setValD(j * channels + 1, clamp(
						(2 * iline.getRown() / rows) - 0.4, 0, 1.0));
				iline.setValD(j * channels + 2, clamp((0.55 * Math.sin(13.0
						* iline.getRown() / rows + j * 25.0 / cols) + 0.5), 0,
						1.0));
			}
			if (alpha)
				addAlpha(iline);
			png.writeRow(iline);
		}
	}

	private void addAlpha(ImageLine iline) {
		int cols = iline.imgInfo.cols;
		int rows = iline.imgInfo.rows;
		for (int i = 0; i < iline.imgInfo.cols; i++) {
			double alpha;
			if (i == 0 || i == iline.imgInfo.cols - 1 || iline.getRown() < 2)
				alpha = 1.0;
			else {
				double d = Math.sqrt(((0.5 * i) / cols + 0.0)
						+ ((0.5 * (rows - iline.getRown())) / rows + 0.0)); // entre
																			// 0
																			// y
																			// 1
				d = d * 1.3 - 0.2;
				alpha = clamp(d, 0.0, 1.0);
			}
			iline.setValD(i * 4 + 3, clamp(alpha, 0, 1.0));
		}
	}

	private double clamp(double d, double d0, double d1) {
		return d > d1 ? d1 : (d < d0 ? d0 : d);
	}
}
